#include "D3DCaptor.h"

BOOL CD3DCaptor::Create(LPCSTR szDeviceName)
{
	strcpy_s(m_RemoteCaptorParam.szDeviceName, 32, szDeviceName);
	if(m_pRpCaptor->CreateRemoteCaptor(m_RemoteCaptorParam))
	{
		DuplicateHandle(m_pRpCaptor->GetRemoteProcess(), 
			m_RemoteCaptorParam.hMutex, GetCurrentProcess(), 
			&m_hMutex, 0, FALSE, DUPLICATE_SAME_ACCESS);

		DuplicateHandle(m_pRpCaptor->GetRemoteProcess(), 
			m_RemoteCaptorParam.hFileMapping, GetCurrentProcess(), 
			&m_hFileMapping, 0, FALSE, DUPLICATE_SAME_ACCESS);

		m_hRemoteCaptor = m_RemoteCaptorParam.hCaptor;
	}

	if(m_hRemoteCaptor)
		m_pCaptorMapping = (FMH_Capture*)MapViewOfFile(m_hFileMapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);

	return m_hRemoteCaptor != NULL;
}

void CD3DCaptor::Destroy()
{
	if (m_pCaptorMapping)
	{
		UnmapViewOfFile(m_pCaptorMapping);
		m_pCaptorMapping = NULL;
	}

	if (m_hFileMapping)
	{
		CloseHandle(m_hFileMapping);
		m_hFileMapping = NULL;
	}

	if (m_hMutex)
	{
		CloseHandle(m_hMutex);
		m_hMutex = NULL;
	}

	if (m_hRemoteCaptor)
	{
		m_pRpCaptor->DestroyRemoteCaptor(m_hRemoteCaptor);
		m_hRemoteCaptor = NULL;
	}
}

BOOL CD3DCaptor::GetChange(D3DFORMAT* pd3dfmt, DWORD* pdwWidth, DWORD* pdwHeight, INT* piPitch, void** ppvBits, RGNDATA** pprd)
{
	if (!m_pCaptorMapping->bDirty) return FALSE;

	WaitForSingleObject(m_hMutex, INFINITE);
	if (m_pCaptorMapping->hFileMapping)
	{
		CloseHandle(m_hFileMapping);
		DuplicateHandle(m_pRpCaptor->GetRemoteProcess(),
			m_pCaptorMapping->hFileMapping, 
			GetCurrentProcess(), 
			&m_hFileMapping, 
			0, 
			FALSE,
			DUPLICATE_SAME_ACCESS);

		m_pCaptorMapping->hFileMapping = NULL;
		UnmapViewOfFile(m_pCaptorMapping);

		m_pCaptorMapping = (FMH_Capture*)MapViewOfFile(m_hFileMapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
	}

	if(m_pCaptorMapping)
	{
		if (pd3dfmt)	*pd3dfmt	= m_pCaptorMapping->dxfmt.d3dfmt;
		if (pdwWidth)	*pdwWidth	= m_pCaptorMapping->dwWidth;
		if (pdwHeight)	*pdwHeight	= m_pCaptorMapping->dwHeight;
		if (piPitch)	*piPitch	= m_pCaptorMapping->iPitch;
		if (ppvBits)	*ppvBits	= (PBYTE)m_pCaptorMapping + m_pCaptorMapping->dwOffsetImage;
		if (pprd)		*pprd		= (RGNDATA*)((PBYTE)m_pCaptorMapping + m_pCaptorMapping->dwOffsetRegion);
		
		return TRUE;
	}

	return FALSE;
}

void CD3DCaptor::CleanChange()
{
	RGNDATA* prd = (RGNDATA*)((PBYTE)m_pCaptorMapping + m_pCaptorMapping->dwOffsetRegion);

	prd->rdh.nCount = 1;
	prd->rdh.nRgnSize = sizeof(RECT);
	prd->rdh.rcBound.left = prd->rdh.rcBound.top = prd->rdh.rcBound.right = prd->rdh.rcBound.bottom = 0;
	ZeroMemory(prd->Buffer, sizeof(RECT));
	m_pCaptorMapping->bDirty = FALSE;

	if(m_hMutex) ReleaseMutex(m_hMutex);
}